package org.eztouch.netty.server;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;

import java.util.Date;

import org.eztouch.netty.base.AskMsg;
import org.eztouch.netty.base.BaseMsg;
import org.eztouch.netty.base.LoginMsg;
import org.eztouch.netty.base.MsgType;
import org.eztouch.netty.base.NettyChannelMap;
import org.eztouch.netty.base.PingMsg;
import org.eztouch.netty.base.ReplyClientBody;
import org.eztouch.netty.base.ReplyMsg;
import org.eztouch.netty.base.ReplyServerBody;

/**
 * netty服务端操作实现类
 *
 */
public class NettyServerHandler extends SimpleChannelInboundHandler<BaseMsg> {

	private int UNCONNECT_NUM_S = 0;

	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
			throws Exception {
		if (evt instanceof IdleStateEvent) {
			if (UNCONNECT_NUM_S >= 4) {
				System.err.println("客户端连接被断开...");
				ctx.close();
				// 此处当重启次数达到4次之后，关闭此链接后，清除服务端相关的记录信息
				return;
			}

			IdleStateEvent e = (IdleStateEvent) evt;
			switch (e.state()) {
			case WRITER_IDLE:
				System.out.println("发送Ping信息到客户端---时间：" + new Date());
				PingMsg pingMsg = new PingMsg();
				ctx.writeAndFlush(pingMsg);
				UNCONNECT_NUM_S++;
				System.err.println("-【服务端】-写超时！！！UNCONNECT_NUM_S=" + UNCONNECT_NUM_S);
				break;
			case READER_IDLE:
				System.err.println("-【服务端】-读超时！！！");
				UNCONNECT_NUM_S++;
				// 读取服务端消息超时时，直接断开该链接，并重新登录请求，建立通道
			case ALL_IDLE:
				System.err.println("-【服务端】-总超时！！！");
				UNCONNECT_NUM_S++;
				// 读取服务端消息超时时，直接断开该链接，并重新登录请求，建立通道
			default:
				break;
			}
		}
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		System.err.println("in channelInactive.");
		NettyChannelMap.remove((SocketChannel) ctx.channel());
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
			throws Exception {

		System.err.println("in here has an error.");
		NettyChannelMap.remove((SocketChannel) ctx.channel());
		super.exceptionCaught(ctx, cause);
		System.err
				.println("channel is exception over. (SocketChannel)ctx.channel()="
						+ (SocketChannel) ctx.channel());
	}

	@Override
	protected void channelRead0(ChannelHandlerContext channelHandlerContext,
			BaseMsg baseMsg) throws Exception {
		System.out.println("-->[服务端]:channelRead0-->msgType:"+baseMsg.getType());
		
		if (MsgType.LOGIN.equals(baseMsg.getType())) {
			LoginMsg loginMsg = (LoginMsg) baseMsg;
			if ("xiaojl".equals(loginMsg.getUserName())
					&& "xiaojl".equals(loginMsg.getPassword())) {
				// 登录成功,把channel存到服务端的map中
				NettyChannelMap.add(loginMsg.getClientId(),(SocketChannel) channelHandlerContext.channel());
				System.out.println("client" + loginMsg.getClientId() + " 登录成功");
			}
		} else {
			if (NettyChannelMap.get(baseMsg.getClientId()) == null) {
				// 说明未登录，或者连接断了，服务器向客户端发起登录请求，让客户端重新登录
				LoginMsg loginMsg = new LoginMsg();
				channelHandlerContext.channel().writeAndFlush(loginMsg);
			}
		}
		switch (baseMsg.getType()) {
		case PING: {
			PingMsg pingMsg = (PingMsg) baseMsg;
			
			System.out.println("接收【客户端】-【PING】信息--->时间：" + new Date());
			
			ReplyMsg replyPing = new ReplyMsg();
			ReplyServerBody body = new ReplyServerBody("【服务端】对Ping的应答信息");
			replyPing.setBody(body);
			NettyChannelMap.get(pingMsg.getClientId()).writeAndFlush(replyPing);
			System.err.println("Ping超时！！！");
		}
			break;
		case ASK: {
			// 收到客户端的请求
			AskMsg askMsg = (AskMsg) baseMsg;
			
			System.out.println("接收【客户端】-【ASK】信息--->内容：" + askMsg.getParams().getContent());
			
			if ("authToken".equals(askMsg.getParams().getAuth())) {
				ReplyServerBody replyBody = new ReplyServerBody("【服务端】对Ask的应答信息");
				ReplyMsg replyMsg = new ReplyMsg();
				replyMsg.setBody(replyBody);
				NettyChannelMap.get(askMsg.getClientId()).writeAndFlush(replyMsg);
			}
		}
			break;
		case REPLY: {
			// 收到客户端回复
			ReplyMsg replyMsg = (ReplyMsg) baseMsg;
			ReplyClientBody clientBody = (ReplyClientBody) replyMsg.getBody();
			UNCONNECT_NUM_S = 0;
			
			System.out.println("接收【客户端】-【REPLY】信息--->内容：" + clientBody.getClientInfo());
		}
			break;
		default:
			break;
		}
		ReferenceCountUtil.release(baseMsg);
	}

}
